Media & interactive Components
Image
- 이미지를 표시하는 컴포넌트
- uri를 이용한 네트워크 이미지 로드 및 로컬 이미지 지원
resizeMode를 사용하여 이미지 크기 조절 가능- 네트워크(API통신을 통한 이미지 호출) 및 로컬 이미지 지원
import { Image, View } from "react-native";
import cat from "./assets/cat.jpg";
export default function App() {
return (
<View style={{ flex: 1 }}>
<Image source={cat} style={{ width: 200, height: 200 }} />
</View>
);
}
declare module "*.jpg";
Image의 source를 이용하여 사진을 불러온다.
source에는 로컬 이미지, API통신을 통한 이미지 호출도 가능하다.
로컬 이미지를 호출 하는 다른 방법 중 하나는 require을 이용하는 것이다.
import { Image, View } from "react-native";
export default function App() {
return (
<View style={{ flex: 1 }}>
<Image
source={require("./assets/cat.png")}
style={{ width: 200, height: 200 }}
/>
</View>
);
}
React Native의 TypeScript버전은 이미지 확장자가 존재하지 않기 때문에
각 확장자에 대해 타입 모듈을 선언하는 방법으로 해결하면 된다.
Image 속성 정리
| 속성 | 타입 | 설명 | 기본값 |
|---|---|---|---|
source | { uri: string } 또는 require("path") | 이미지 소스 지정 (네트워크 또는 로컬) | 필수 |
resizeMode | "cover" "contain" "stretch" "repeat" "center" | 이미지 크기 조절 방식 | "cover" |
style | StyleProp<ImageStyle> | 스타일 적용 (width, height 필수) | undefined |
onLoad | () => void | 이미지가 로드될 때 실행할 함수 | undefined |
onError | (error) => void | 이미지 로드 실패 시 실행할 함수 | undefined |
onLoadStart | () => void | 이미지 로드 시작 시 실행할 함수 | undefined |
onLoadEnd | () => void | 이미지 로드 완료 후 실행할 함수 | undefined |
onProgress | (event) => void | 로드 중인 이미지의 진행 상태 반환 | undefined |
fadeDuration | number | Android에서 이미지가 로드될 때의 페이드 효과 (ms) | 300 |
defaultSource | ImageSourcePropType | 로드되기 전 표시할 기본 이미지 (iOS) | undefined |
blurRadius | number | 블러 효과 적용 (숫자가 클수록 흐려짐) | 0 |
tintColor | string | 이미지 색상 필터 적용 | undefined |
- resizeMode 속성 값 설명
| 값 | 설명 |
|---|---|
cover | 원본 비율을 유지하면서 컨테이너를 채움 (잘릴 수 있음) |
contain | 원본 비율을 유지하면서 컨테이너 내에 맞춤 (잘리지 않음) |
stretch | 원본 비율을 무시하고 컨테이너에 맞춤 |
center | 원본 크기를 유지하며 중앙 정렬 |
repeat | 이미지가 반복되도록 설정 (iOS only) |
ImageBackground
- 이미지를 배경으로 설정할 때 사용하는 컴포넌트
- Image와 다르게
children을 포함 가능 - Image와 같이
resizeMode를 사용하여 이미지 크기 조절 가능
import { ImageBackground, SafeAreaView, Text } from "react-native";
import cat from "./assets/cat.jpg";
export default function App() {
return (
<SafeAreaView
style={{
flex: 1,
}}
>
<ImageBackground source={cat} style={{ flex: 1 }}>
<Text style={{ color: "yellow", fontSize: 30 }}>Cat is Cute</Text>
</ImageBackground>
</SafeAreaView>
);
}
declare module "*.jpg";
<Image>태그와 다르게 <ImageBackground>태그는 배경으로 사용을 하며,
하위 태그에 다른 태그를 사용가능하다.
Image에서 작성된 속성과 동일하게 사용할 수 있다.
TouchableWithoutFeedback
- 터치 이벤트를 감지하지만, 기본적인 피드백(애니메이션 효과 등)은 제공하지 않는 컴포넌트
- 키보드 숨기기, 모달 외부 클릭 감지 등에 유용하게 사용
import {
View,
Image,
SafeAreaView,
TouchableWithoutFeedback,
} from "react-native";
export default function App() {
return (
<SafeAreaView style={{ flex: 1 }}>
<TouchableWithoutFeedback
onPress={() => console.log("이미지 외부 클릭!")}
>
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}
>
<TouchableWithoutFeedback onPress={() => console.log("이미지 클릭!")}>
<Image
source={require("./assets/cat.jpg")}
style={{ width: "50%", height: "50%" }}
/>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
</SafeAreaView>
);
}
이미지를 클릭할 경우, 이미지 클릭!이 출력,
이미지 밖을 클릭할 경우, 이미지 외부 클릭!이 출력된다.
TouchableWithoutFeedback을 이용하여 이벤트를 처리할 영역마다 감싸주면 된다.
import { useState } from "react";
import {
View,
SafeAreaView,
TouchableWithoutFeedback,
TextInput,
Keyboard,
Text,
} from "react-native";
export default function App() {
const [text, setText] = useState<string>("");
return (
<SafeAreaView style={{ flex: 1 }}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
gap: 10,
}}
>
<TouchableWithoutFeedback>
<TextInput
placeholder="값 입력"
onChangeText={(e) => setText(e)}
style={{
width: "50%",
borderWidth: 2,
borderColor: "#3498db",
borderRadius: 8,
}}
/>
</TouchableWithoutFeedback>
<Text>{text}</Text>
</View>
</TouchableWithoutFeedback>
</SafeAreaView>
);
}
TextInput을 제외한 나머지 영역을 TouchableWithoutFeedback으로 감싼 후,
onPress에 Keyboard.dismiss를 설정하면,
사용자가 TextInput 외부를 터치할 때 키보드가 자동으로 닫힌다.
단, TouchableWithoutFeedback으로 감싸더라도 내부 요소(TextInput)가
터치 이벤트를 계속 받을 수 있도록 accessible={false} 를 추가하는 것이 좋다.
TouchableWithoutFeedback 속성 정리
| 속성명 | 타입 | 기본값 | 설명 |
|---|---|---|---|
onPress | () => void | 터치 이벤트 발생 시 실행할 함수 | |
accessible | boolean | true | false로 설정하면 내부 요소가 접근성 요소로 인식되지 않음 (이벤트 방해 방지) |
disabled | boolean | false | true이면 터치 이벤트가 비활성화됨 |
hitSlop | { top, left, bottom, right } | undefined | 터치 영역을 확장하거나 축소할 수 있음 |
onPressIn | () => void | 터치가 시작될 때 실행되는 함수 | |
onPressOut | () => void | 터치가 끝났을 때 실행되는 함수 | |
keyboardShouldPersistTaps | "always" "handled" "never" | "never" | 터치 시 키보드 유지 여부 설정 |
Modal
- React Native에서 화면 위에 새로운 뷰를 띄우는 컴포넌트
- 팝업, 다이얼로그, 알림창 등을 만들 때 사용
import { useState } from "react";
import {
Modal,
View,
Image,
Button,
SafeAreaView,
TouchableWithoutFeedback,
} from "react-native";
export default function App() {
const [modalVisible, setModalVisible] = useState(false);
return (
<SafeAreaView
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
>
<Button title="모달 열기" onPress={() => setModalVisible(true)} />
<Modal visible={modalVisible} animationType="slide" transparent={true}>
<TouchableWithoutFeedback
onPress={() => setModalVisible(!modalVisible)}
>
<View
style={{
flex: 1,
backgroundColor: "rgba(0,0,0,0.5)",
justifyContent: "center",
alignItems: "center",
}}
>
<TouchableWithoutFeedback>
<Image
source={require("./assets/cat.jpg")}
style={{ width: "50%", height: "50%" }}
/>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
</Modal>
</SafeAreaView>
);
}
Modal의 열림/닫힘을 관리하기 위해 useState를 사용한다.
Modal은 React Native의 최상의 뷰에서 동작하는 독립적인 컴포넌트이기 때문에
Button과 같은 위치에 코드를 작성해도 동작에 문제가 없다.
Modal이 열린 후, Image영역 외의 배경을 클릭하면 Modal이 닫히도록 TouchableWithoutFeedback을 사용하였다.
이때, TouchableWithoutFeedback을 중첩하여 이미지 클릭 시에는 닫히지 않도록 처리했다.
Modal 속성 정리
| 속성명 | 타입 | 기본값 | 설명 |
|---|---|---|---|
visible | boolean | false | 모달 표시 여부 |
animationType | "none" "slide" "fade" | none | 모달이 열릴 때 애니메이션 효과 |
transparent | boolean | false | 모달 배경을 투명하게 설정 |
onRequestClose | () => void | 안드로이드에서 뒤로 가기 버튼을 눌렀을 때 실행 | |
presentationStyle | "fullScreen" "pageSheet" "formSheet" "overFullScreen" | fullScreen | iOS에서 모달 스타일 지정 |
ActivityIndicator
- 로딩 상태를 표시하는 기본적인 UI 컴포넌트
- 실제 로딩을 표현하는 것이 아닌 시각적인 피드백만 제공
import { useState } from "react";
import { ActivityIndicator, View, Button } from "react-native";
export default function App() {
const [loading, setLoading] = useState(false);
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
gap: 20,
}}
>
<View style={{ flexDirection: "row", gap: 20 }}>
<Button title="로딩 시작" onPress={() => setLoading(true)} />
<Button title="로딩 종료" onPress={() => setLoading(false)} />
</View>
{loading && <ActivityIndicator size={100} color="pink" />}
</View>
);
}
위의 실행 화면과 같이 사용자에게 로딩 중임을 시각적으로 전달한다.
따라서, 데이터 로딩을 표현해야할 경우 useState 등을 활용하여 로딩 상태를 관리하면서 표시해야 한다.
ActivityIndicator 속성 정리
| 속성명 |
|---|